home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / packet / p_aa4re / mbb35src / mbbload.asm < prev    next >
Encoding:
Assembly Source File  |  1991-02-16  |  17.9 KB  |  410 lines

  1. ;==========================================================================;
  2. ; Resident loader handler                                                  ;
  3. ;                                                                          ;
  4. ;   Copyright 1986, 1987, 1991 by H. Roy Engehausen.  All rights reserved. ;
  5. ;   This software may be freely distributed and used, but it may not       ;
  6. ;   under any circumstances be sold by anyone other than the author.       ;
  7. ;   It may be distributed by a commercial company as long as it is         ;
  8. ;   for no cost.                                                           ;
  9. ;                                                                          ;
  10. ;==========================================================================;
  11.  
  12. ;==========================================================================;
  13. ; Process the parameter list                                               ;
  14. ;==========================================================================;
  15.  
  16.         MOV     parm_flag,0         ; Start with zeros
  17.  
  18.         SUB     BX,BX               ; Start at front of parameter
  19.  
  20. parm_loop:                          ; Do make things easier, we have
  21.                                     ; DI with 1 higher than we really want
  22.  
  23.         CMP     BL,psp_parm_len     ; Are we done?
  24.         JGE     parm_end            ;      Yes...
  25.  
  26.         INC     BX                  ;
  27.  
  28.         CMP     psp_parm-1[BX],' '  ; Ignore blanks
  29.         JE      parm_loop           ;
  30.  
  31.         CMP     psp_parm-1[BX],'/'  ; Ignore "/"
  32.         JE      parm_loop           ;
  33.  
  34.         CMP     psp_parm-1[BX],'f'  ; Handle "f"
  35.         JE      parm_is_f           ;
  36.         CMP     psp_parm-1[BX],'F'  ; Handle "F"
  37.         JNE     parm_not_f          ;
  38. parm_is_f:
  39.         OR      parm_flag,parm_flag_f ;
  40.         JMP     parm_loop           ;
  41. parm_not_f:
  42.  
  43.         CMP     psp_parm-1[BX],'r'  ; Handle "r"
  44.         JE      parm_is_r           ;
  45.         CMP     psp_parm-1[BX],'R'  ; Handle "R"
  46.         JNE     parm_not_r          ;
  47. parm_is_r:
  48.         OR      parm_flag,parm_flag_r ;
  49.         JMP     parm_loop           ;
  50. parm_not_r:
  51.  
  52.         CMP     psp_parm-1[BX],'u'  ; Handle "u"
  53.         JE      parm_is_u           ;
  54.         CMP     psp_parm-1[BX],'U'  ; Handle "U"
  55.         JNE     parm_not_u          ;
  56. parm_is_u:
  57.         OR      parm_flag,parm_flag_u ;
  58.         JMP     parm_loop           ;
  59. parm_not_u:
  60.  
  61.         CMP     psp_parm-1[BX],'d'  ; Handle "d"
  62.         JE      parm_is_d           ;
  63.         CMP     psp_parm-1[BX],'D'  ; Handle "D"
  64.         JNE     parm_not_d          ;
  65. parm_is_d:
  66.         OR      parm_flag,parm_flag_d ;
  67.         JMP     parm_loop           ;
  68. parm_not_d:
  69.  
  70. ; Invalid character if we get here
  71.  
  72.         MOV     DX,OFFSET msgbad    ; Message
  73.         MOV     AH,dos_write_line   ; Send to output
  74.         INT     dos_vector_no       ;
  75.  
  76.         INT     dos_terminate_no    ; Terminate!
  77.  
  78. parm_end:                           ;
  79.  
  80. ;==========================================================================;
  81. ; See if we already have a copy of this program resident                   ;
  82. ;==========================================================================;
  83.  
  84. ;--------------------------------------------------------------------------;
  85. ; Using the parent PSP pointer, loop back until we find a block that       ;
  86. ; points to itself.  This belongs the the command executor (COMMAND.COM)   ;
  87. ;--------------------------------------------------------------------------;
  88.  
  89. ; CS assumed to point to current PSP
  90.  
  91.         MOV     AX,CS               ; Put current PSP pointer
  92.         MOV     ES,AX               ; into ES
  93.  
  94. psplp:
  95.         MOV     AX,WORD PTR ES:16H  ; parent pointer
  96.  
  97.         MOV     BX,ES               ; Compare current PSP to parent PSP
  98.         CMP     AX,BX               ;
  99.         JZ      pspfnd              ; Both are the same, we have located
  100.         MOV     ES,AX               ; COMMAND.COM
  101.         JMP     psplp               ;
  102.  
  103. pspfnd:                             ; here ES points to COMMAND.COM PSP
  104.  
  105. ;--------------------------------------------------------------------------;
  106. ; The next step is to scan the memory block chain, looking to see if any   ;
  107. ; of them belong to a resident copy of our program.                        ;
  108. ;                                                                          ;
  109. ; The storage management routines in DOS build and maintain a set of       ;
  110. ; contiguous memory blocks.  Each block is prefixed by 16 bytes of control ;
  111. ; information.  The block might contain a program (with a PSP at the       ;
  112. ; front) or an Environment string (every program gets one of these when    ;
  113. ; it's loaded to hold things like the full path name by which it was       ;
  114. ; loaded) or some real data (since a program can request some storage from ;
  115. ; DOS and use it for any purpose it likes).  The first 5 bytes of the      ;
  116. ; control information contain:                                             ;
  117. ;                                                                          ;
  118. ;    Offset       Contents                                                 ;                                                                          ;
  119. ;      0          flag byte (Z = last in chain, M = middle)                ;                                                                          ;
  120. ;      1          2 byte pointer to owning PSP (0 means                    ;                                                                          ;
  121. ;                 this block is unallocated)                               ;                                                                          ;
  122. ;      3          size of this block in paragraphs (size                   ;                                                                          ;
  123. ;                 does not include the control information)                ;                                                                          ;
  124. ;                                                                          ;                                                                          ;
  125. ; Note that these fields are also UNDOCUMENTED.                            ;                                                                          ;
  126. ;                                                                          ;                                                                          ;
  127. ; Since the memory blocks are contiguous, it's easy to use the size at     ;                                                                          ;
  128. ; offset 3 to step through the chain.                                      ;                                                                          ;
  129. ;                                                                          ;                                                                          ;
  130. ; We will only search blocks that are owned by COMMAND.COM's PSP.          ;                                                                          ;
  131. ;                                                                          ;                                                                          ;
  132. ;--------------------------------------------------------------------------;
  133.  
  134. ; assumes es still points to COMMAND.COM's PSP
  135.  
  136.         MOV     DX,-1               ; Indicate not found
  137.         MOV     BX,ES
  138.         DEC     BX                  ; Point to memory block
  139.         MOV     ES,BX
  140.  
  141. memlp:
  142.  
  143. ; Loop to here to check a memory block.
  144.  
  145.         CMP     BYTE PTR ES:0,'Z'   ; are we at the end?
  146.         JZ      memex               ;      Exit if yes
  147.         MOV     AX,WORD PTR es:1    ; PSP of owning prog
  148.         DEC     AX                  ; Memory block
  149.         CMP     AX,BX               ; Does block contain a PSP owned by
  150.         JNZ     memnxt              ;      No...  go to next one
  151.         INC     AX                  ; Yes, the back to psp
  152.  
  153. ; here we have a PSP pointed to by AX
  154.  
  155.         MOV     BX,CS               ; Get my PSP address
  156.         CMP     AX,BX               ; Is it me?
  157.         JZ      memex               ;      Yes... Exit!
  158.  
  159. ; here we have a PSP pointed to by AX, so we test if it is
  160. ; a copy of us by comparing a string of characters in us
  161. ; with the same string in it. Once again we assume that
  162. ; assume that MARKER is a label at the start of the string
  163. ; and that MARKLEN is the length of the string.
  164.  
  165.         INC     psp_count           ; Bump the PSP counter
  166.  
  167.         PUSH    ES                  ; Save current es
  168.  
  169.         MOV     ES,AX               ; We will compare the program pointed to
  170.                                     ; by ES with ourselves pointed to by DS
  171.  
  172.         MOV     SI,OFFSET marker    ; Same offset for marker for both segments
  173.         MOV     DI,SI               ;
  174.  
  175.         CLD                         ;
  176.  
  177.         MOV     CX,marklen          ; Length of fixed text
  178.         REPE    cmpsb               ; Compare strings
  179.         JNZ     memnotus            ; It is not us
  180.  
  181.         MOV     psp_count,0         ; Clear the PSP counter
  182.         MOV     DX,ES               ; And save pointer to resident copy
  183.  
  184. memnotus:
  185.  
  186.         POP     ES                  ; It's not so restore es
  187.                                     ; And continue
  188.  
  189. memnxt:
  190.  
  191.         MOV     AX,ES:3             ; Size of this block
  192.         MOV     BX,ES               ; Pointer to this block
  193.         ADD     BX,AX               ;
  194.         INC     BX                  ; Add 1 for control info p'graph
  195.         MOV     ES,BX               ; Point to next mem ctrl block
  196.         jmp     memlp               ; And the loop back
  197.  
  198. memyes:
  199.         MOV     DX,ES               ; save pointer to resident copy
  200.         POP     ES                  ;
  201.  
  202. memex:                              ;
  203.  
  204. ; DX = -1 for resident copy not found
  205. ; DX = segment if we found the resident copy
  206. ; psp_count = Number of programs loaded after us
  207.  
  208. ;==========================================================================;
  209. ; Check for duplicate load!  Send error message and terminate as           ;
  210. ; appropriate                                                              ;
  211. ;==========================================================================;
  212.  
  213.         CMP     DX,-1               ; Not found?
  214.         JE      no_dupe_load        ;      That's right!
  215.  
  216.         TEST    parm_flag,parm_flag_u ; Unload?
  217.         JNZ     no_dupe_load        ;      That's right!
  218.         TEST    parm_flag,parm_flag_f ; Duplicates allowed?
  219.         JNZ     no_dupe_load        ;      That's right!
  220.  
  221. ; Error -- We found a copy but it wasn't permitted
  222.  
  223.         MOV     DX,OFFSET msgdupe   ; Message
  224.         MOV     AH,dos_write_line   ; Send to output
  225.         INT     dos_vector_no       ;
  226.  
  227.         INT     dos_terminate_no    ; Terminate!
  228.  
  229. no_dupe_load:
  230.  
  231. ;==========================================================================;
  232. ; Handle unload!                                                           ;
  233. ;==========================================================================;
  234.  
  235.         TEST    parm_flag,parm_flag_u ; Unload?
  236.         JNZ     unload_to_do        ;
  237.         JMP     no_unload           ;      Nope............
  238.  
  239. unload_to_do:
  240.  
  241. ;--------------------------------------------------------------------------;
  242. ; If we are not found then we can unload -- Give an error                  ;
  243. ;--------------------------------------------------------------------------;
  244.  
  245.         CMP     DX,-1               ; Not found?
  246.         JNE     unload_found        ;      Nope............
  247.  
  248. ; Error -- Unload but we can't find ourselves!
  249.  
  250.         MOV     DX,OFFSET msgnodup  ; Message
  251.         MOV     AH,dos_write_line   ; Send to output
  252.         INT     dos_vector_no       ;
  253.  
  254.         INT     dos_terminate_no    ; Terminate!
  255.  
  256. unload_found:
  257.  
  258. ;--------------------------------------------------------------------------;
  259. ; If we are not the last guy in the chain, give an error                   ;
  260. ;--------------------------------------------------------------------------;
  261.  
  262.         CMP     psp_count,0         ; Any PSPs after us
  263.         JE      unload_last         ;      Nope............
  264.  
  265. ; Error -- Unload but we are not last in chain
  266.  
  267.         MOV     DX,OFFSET msgnotlast; Message
  268.         MOV     AH,dos_write_line   ; Send to output
  269.         INT     dos_vector_no       ;
  270.  
  271.         INT     dos_terminate_no    ; Terminate!
  272.  
  273. unload_last:
  274.  
  275. ;--------------------------------------------------------------------------;
  276. ; Unchain the interrupts that we have chained!                             ;
  277. ;--------------------------------------------------------------------------;
  278.  
  279.         MOV     BX,DX               ; BX = segment of copy we are unloading
  280.         CLI                         ; No interrupts please
  281.  
  282. ;--------------------------------------------------------------------------;
  283. ; Unchain the main interrupt                                               ;
  284. ;--------------------------------------------------------------------------;
  285.  
  286.         MOV     ES,BX               ; Get segment to be unloaded
  287.  
  288.         PUSH    DS                  ; Save DS
  289.  
  290.         MOV     DX,ES:old_bios_vector    ; Get old vector
  291.         MOV     DS,ES:old_bios_vector+2  ;
  292.  
  293.         MOV     AL,rs232_vector_no  ; vector #
  294.  
  295.         MOV     AH,dos_set_vector   ; DOS call #25H -- Set vector
  296.         INT     dos_vector_no       ; Do it
  297.  
  298.         POP     DS                  ; Restore DS
  299.  
  300. ;--------------------------------------------------------------------------;
  301. ; Loop thru all the com blocks                                             ;
  302. ;--------------------------------------------------------------------------;
  303.  
  304.         MOV     SI,OFFSET com_start ; Place to start the comm loop
  305.  
  306. unload_loop:
  307.  
  308.         MOV     DI,com_init_count   ; Get number of ports left to do
  309.  
  310. ;--------------------------------------------------------------------------;
  311. ; Unchain the vector                                                       ;
  312. ;--------------------------------------------------------------------------;
  313.  
  314.         MOV     ES,BX               ; Get segment to be unloaded
  315.  
  316.         MOV     DX,ES:old_interrupt_vec_off[DI] ; Get previous offset
  317.         MOV     AX,ES:old_interrupt_vec_seg[DI] ; Get previous segment
  318.  
  319.         OR      AX,AX               ; Test to see if used
  320.         JZ      unload_no_int       ; No interrupt here
  321.  
  322.         PUSH    DS                  ; Save DS
  323.         MOV     DS,AX               ; Set DS to segement of interrupt guy
  324.  
  325.         MOV     AL,ES:hiv[SI]       ; Get the hardware interrupt vector address
  326.  
  327.         MOV     AH,dos_set_vector   ; DOS call #25H -- Set vector
  328.         INT     dos_vector_no       ; Do it
  329.  
  330.         POP     DS                  ; Restore DS
  331.  
  332. unload_no_int:
  333.  
  334.         INC     DI                  ; Bump counter
  335.         INC     DI                  ; Twice for words
  336.         MOV     com_init_count,DI   ; and then save it
  337.  
  338. ;--------------------------------------------------------------------------;
  339. ; Loop thru the next comm port                                             ;
  340. ;--------------------------------------------------------------------------;
  341.  
  342.         MOV     SI,com_next[SI]     ; Pointer to next com port block
  343.  
  344.         CMP     SI,0                ; Anything left to be done?
  345.         JE      unload_intr_done    ;      Nope...
  346.         JMP     unload_loop         ;      Yep.. Loop back
  347.  
  348. unload_intr_done:
  349.  
  350. ;--------------------------------------------------------------------------;
  351. ; Unchain the timer interrupt                                              ;
  352. ;--------------------------------------------------------------------------;
  353.  
  354.  
  355.         MOV     DX,ES:timer_old     ; Get previous offset
  356.         MOV     AX,ES:timer_old+2   ; Get previous segment
  357.  
  358.         OR      AX,AX               ; Was it snatched?
  359.         JZ      unload_no_timer     ; Nope
  360.  
  361.         PUSH    DS                  ; Save DS
  362.         MOV     DS,AX               ; Set DS to segement of interrupt guy
  363.  
  364.         MOV     AH,dos_set_vector   ; DOS call #25H -- Set vector
  365.         MOV     AL,timer_vector_no  ; Timer vector #
  366.         INT     dos_vector_no       ; Do it
  367.  
  368.         POP     DS                  ; Restore DS
  369.  
  370. unload_no_timer:                    ;
  371.  
  372. ;--------------------------------------------------------------------------;
  373. ; Enable interrupts                                                        ;
  374. ;--------------------------------------------------------------------------;
  375.  
  376.         STI                         ; Enable CPU to receive interupts
  377.  
  378. ;--------------------------------------------------------------------------;
  379. ; Successful unload message here                                           ;
  380. ;--------------------------------------------------------------------------;
  381.  
  382.         MOV     DX,OFFSET msgunload ; Message
  383.         MOV     AH,dos_write_line   ; Send to output
  384.         INT     dos_vector_no       ;
  385.  
  386. ;--------------------------------------------------------------------------;
  387. ; Now free the program whose PSP is pointed to by DX                       ;
  388. ;--------------------------------------------------------------------------;
  389.  
  390.         MOV     ES,BX               ; Point to PSP to be dropped
  391.         MOV     AH,dos_free_mem     ;
  392.         INT     dos_vector_no       ; Free it
  393.  
  394.         MOV     ES,ES:psp_environ_ptr ; Segment address of environment
  395.         MOV     AH,dos_free_mem     ;
  396.         INT     dos_vector_no       ; Free it
  397.  
  398. ;--------------------------------------------------------------------------;
  399. ; Unload complete                                                          ;
  400. ;--------------------------------------------------------------------------;
  401.  
  402.         INT     dos_terminate_no    ; Terminate!
  403.  
  404. ;==========================================================================;
  405. ; Handle reset                                                             ;
  406. ;==========================================================================;
  407.  
  408. no_unload:
  409.  
  410.